package com.lidx.back.statistics.service.impl;

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;

import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;

import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPClientConfig;
import org.apache.commons.net.ftp.FTPFile;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;
import org.springframework.util.FileCopyUtils;
import org.springframework.util.FileSystemUtils;
import org.springframework.util.StringUtils;

import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.google.common.io.Files;
import com.google.gson.Gson;
import com.lidx.back.statistics.commons.Constants;
import com.lidx.back.statistics.commons.MaterialUpdateConfig;
import com.lidx.back.statistics.controller.MaterialUpdateRequestBean;
import com.lidx.back.statistics.controller.admin.MaterialIconJson;
import com.lidx.back.statistics.dao.IAppInitDao;
import com.lidx.back.statistics.dao.IMaterialDao;
import com.lidx.back.statistics.entity.ClientInfo;
import com.lidx.back.statistics.entity.MaterialPO;
import com.lidx.back.statistics.entity.MaterialUpdateRequestInfo;
import com.lidx.back.statistics.service.IMaterialService;
import com.lidx.back.statistics.utils.EhCacheUtils;
import com.lidx.back.statistics.utils.FileUtils;
import com.lidx.back.statistics.utils.JedisUtils;
@Service
@Transactional
public class MaterialServiceImpl implements IMaterialService {

	private static final Logger logger = LoggerFactory.getLogger(MaterialServiceImpl.class);
	
	@Autowired
	private IMaterialDao materialDao;
	@Autowired
	private IAppInitDao appInitDao;
	@Autowired
	private MaterialUpdateConfig materialUpdateConfig;
	@Transactional(readOnly=true)
	public List<MaterialPO> findAllMaterialList(String versionType, String versionNumber) {
		/*JSONObject jsonObject = new JSONObject();
		String materialJsonString = JedisUtils.get(Constants.REDIS_MATERIAL_LIST_KEY+versionType+versionNumber);
		if(!StringUtils.isEmpty(materialJsonString)){
			Object list = jsonObject.parseArray(materialJsonString, MaterialPO.class);
			if(list instanceof List){
				List<MaterialPO> redisMaterialList = (List)list;
				return redisMaterialList;
			}
		}*/
		List<MaterialPO> redisMaterials = materialDao.getAllMaterialPOs(versionType, versionNumber);
		/*materialJsonString = jsonObject.toJSONString(redisMaterials);
		JedisUtils.set(Constants.REDIS_MATERIAL_LIST_KEY+versionType+versionNumber, materialJsonString, 60*60);*/
		return redisMaterials;
	}

	public List<MaterialPO> findRecommendMaterials(String versionType,
			String versionNumber, String deviceId) {
		ClientInfo clientInfo = appInitDao.getClientInfo(deviceId);
		String sex = clientInfo.getSex();
		List<MaterialPO> materialPOs = materialDao.getRecommendMaterialPOs(versionType, versionNumber, sex);
		if(materialPOs != null)
			return materialPOs;
		return new ArrayList<MaterialPO>();
	}

	public void updateMaterialUpdateRequest(MaterialUpdateRequestInfo info) {
		info.setId(1);
		materialDao.updateRequest(info);
	}

	public MaterialUpdateRequestInfo getRequestInfo() {
		return materialDao.getRequestInfo();
	}

	@Transactional(readOnly=false,rollbackFor=Exception.class)
	public synchronized void updateMaterial(String versionType, String versionNumber) throws Exception {
		// 准备相关目录
		String workspaceRoot = materialUpdateConfig.getLocalWorkspace();
		if (!new File(workspaceRoot).exists()) {
			new File(workspaceRoot).mkdirs();
			if (!new File(workspaceRoot).exists()) {
				throw new Exception("workspaceRoot not exist: " + workspaceRoot);
			}
		}
		// 下载SVN目录
				/*File svnFolder = downloadFromSVN(svnRoot, svnRevision, workspaceRoot);
				logger.info("svnFolder.getAbsolutePath() ====" + svnFolder.getAbsolutePath());*/
		FTPClient ftpClient = new FTPClient();
		ftpClient.connect(materialUpdateConfig.getIisFtpHost());

		ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
		ftpClient.setControlEncoding("utf-8");
		ftpClient.setControlKeepAliveReplyTimeout(300000);
		ftpClient.setConnectTimeout(300000);
		ftpClient.setControlKeepAliveTimeout(300000);
		ftpClient.enterLocalPassiveMode();
		
		ftpClient.configure(new FTPClientConfig("com.zznode.tnms.ra.c11n.nj.resource.ftp.UnixFTPEntryParser"));
		boolean loginResult = ftpClient.login(materialUpdateConfig.getFtpUserName(), materialUpdateConfig.getFtpPassword());
		if (!loginResult) {
			throw new Exception("ftp login failed. " + materialUpdateConfig.getIisFtpHost());
		}
		
		String destFolderPath = workspaceRoot + DateFormatUtils.format(System.currentTimeMillis(), "yyyyMMddHHmmss");
		File destFolder = new File(destFolderPath);
		if (destFolder.exists()) {
			throw new Exception("not empty folder.");
		} else {
			destFolder.mkdirs();
		}
		
		boolean ftpChangeResult = ftpClient.changeWorkingDirectory(materialUpdateConfig.getIisFtpRoot()+versionType+"/"+versionNumber);
		
		FTPFile[] fs = ftpClient.listFiles(); 
        for(FTPFile ff:fs){ 
                File localFile = new File(destFolderPath+"/"+ff.getName()); 
                 
                OutputStream is = new FileOutputStream(localFile);  
                ftpClient.retrieveFile(ff.getName(), is); 
                is.close(); 
        } 
        List<MaterialUpdateRequestBean> materialRequests = parseMateralsInFolder(destFolder,versionType,versionNumber);
        
        StringBuffer sb = new StringBuffer();
        List<MaterialIconJson> jsons = Lists.newArrayList();
        for (MaterialUpdateRequestBean request : materialRequests) {
        	MaterialIconJson iconJson = new MaterialIconJson();
        	// icon
			File iconFile = request.getIconFile();
			String iconName = iconFile.getName();
			byte[] iconBytes = FileCopyUtils.copyToByteArray(iconFile);
			String iconMD5 = DigestUtils.md5DigestAsHex(iconBytes);
			String iconDownloadUrl = materialUpdateConfig.getIisURLRoot() + versionType + "/" + versionNumber + "/" + iconName;

			request.getMaterialPo().setIconName(iconName);
			request.getMaterialPo().setIconMD5(iconMD5);
			request.getMaterialPo().setIconDownloadUrl(iconDownloadUrl);
			
			iconJson.setIconMD5(iconMD5);
			iconJson.setIconName(iconName);
			iconJson.setCategory(request.getMaterialPo().getCategory());
			iconJson.setIsRecommend(request.getMaterialPo().getIsRecommend());
			iconJson.setRecommendOrder(request.getMaterialPo().getRecommendOrder());
			iconJson.setCategoryOrder(request.getMaterialPo().getCategoryOrder());
			jsons.add(iconJson);
			// material
			File materialFile = request.getMaterialFile();
			String materialName = materialFile.getName();
			byte[] materialBytes = FileCopyUtils.copyToByteArray(materialFile);
			String materialMD5 = DigestUtils.md5DigestAsHex(materialBytes);

			String materialDownloadUrl = materialUpdateConfig.getIisURLRoot() + versionType + "/" + versionNumber + "/" + materialName;

			request.getMaterialPo().setMaterialName(materialName);
			request.getMaterialPo().setMaterialMD5(materialMD5);
			request.getMaterialPo().setMaterialDownloadUrl(materialDownloadUrl);
			//BeanCopyUtils.copyAllPropertiesTo(source, target);
			
			Gson gson = new Gson();
			//String singleJson = gson.toJson(iconJson);
		} 
        Gson gson = new Gson();
        String outJson = gson.toJson(jsons);
        FileUtils.writeToFile("d:\\jsonfile\\jsonFile.txt", outJson, false);
        
		// 更新数据库：删除原版本相关素材积累，全部插入新纪录
		materialDao.deleteMaterials(versionType, versionNumber);
		for (MaterialUpdateRequestBean request : materialRequests) {
			MaterialPO materialPo = request.getMaterialPo();
			
			materialDao.saveMaterial(materialPo);
			//materialService.updateMaterialById(materialPo, materialPo.getId());
		}
		
		/*CacheManager cacheManager = EhCacheUtils.getCacheManager();
		Cache materialCache= cacheManager.getCache("materialPO");
		Object o = materialCache.get("materials"+versionType+versionNumber);
		materialCache.remove("materials"+versionType+versionNumber);
		EhCacheUtils.put("materialPO", "materials"+versionType+versionNumber, materialDao.getAllMaterialPOs(versionType, versionNumber));*/
		
		logger.debug("database update finished",materialRequests);

		FileSystemUtils.deleteRecursively(destFolder);
		ftpClient.disconnect();
	}
	
	private List<MaterialUpdateRequestBean> parseMateralsInFolder(File folder, String versionType, String versionNumber) throws Exception {

		if (folder == null || !folder.exists() || !folder.canRead()) {
			throw new Exception("目录读取异常！" + folder);
		}

		File configFile = new File(folder.getAbsolutePath() + "\\" + materialUpdateConfig.getConfigFileName());

		if (!configFile.exists() || !configFile.canRead()) {
			throw new Exception("配置文件读取异常！" + configFile);
		}

		// 读文件
		Charset charset = Charset.forName("utf-8");
		List<String> lines = new ArrayList<String>();
		try {
			lines = Files.readLines(configFile, charset);
		} catch (Exception e) {
			throw new Exception("素材配置文件读取异常！");
		}

		// 版本类型
		/*String versionType = "";
		{
			try {
				String versionTypeStr = lines.get(1);
				if ("ios".equalsIgnoreCase(versionTypeStr)) {
					versionType = "ios";
				} else if ("android".equalsIgnoreCase(versionTypeStr)) {
					versionType = "android";
				} else {
					throw new Exception();
				}
			} catch (Exception e) {
				throw new Exception("素材配置文件中版本类型错误！" + versionType);
			}
		}*/

		// 版本号
		/*String versionNumber = "";
		{
			String versionNumStr = lines.get(3);
			if (versionNumStr != null && !StringUtils.isEmpty(versionNumStr.trim())) {
				versionNumber = versionNumStr.trim();
			} else {
				throw new Exception("素材配置文件中版本号错误！");
			}
		}*/

		// 素材文件
		List<MaterialUpdateRequestBean> materialRequests = new ArrayList<MaterialUpdateRequestBean>();
		{
			try {
				for (int i = 1; i < lines.size(); i++) {
					MaterialUpdateRequestBean materialRequest = new MaterialUpdateRequestBean();
					String lineStr = lines.get(i);
					if (lineStr != null && !StringUtils.isEmpty(lineStr.trim())) {
						String[] parts = lineStr.split(";");
						if (parts.length != 8) {
							throw new Exception("素材列表数据格式错误  == " + lineStr);
						}

						String uuid = parts[0].trim();
						if (!StringUtils.isEmpty(uuid)) {
							materialRequest.getMaterialPo().setUuid(uuid);
						} else {
							throw new Exception("UUID的参数值为空！  ==" + lineStr);
						}

						String iconName = parts[1].trim();
						File iconFile = new File(folder.getAbsolutePath() + "\\" + iconName);
						if (iconFile.exists()) {
							materialRequest.setIconFile(iconFile);
						} else {
							throw new Exception(iconName + "不存在！  ==" + lineStr);
						}

						String materialName = parts[2].trim();
						File materialFile = new File(folder.getAbsolutePath() + "\\" + materialName);
						if (materialFile.exists()) {
							materialRequest.setMaterialFile(materialFile);
						} else {
							throw new Exception(materialName + "不存在！  ==" + lineStr);
						}

						String isRecommend = parts[3].trim();
						String recommendOrder = parts[4].trim();
						if ("y".equalsIgnoreCase(isRecommend) && !StringUtils.isEmpty(recommendOrder)) {
							materialRequest.getMaterialPo().setIsRecommend("1");
							materialRequest.getMaterialPo().setRecommendOrder(recommendOrder);
						} else if ("n".equalsIgnoreCase(isRecommend)) {
							materialRequest.getMaterialPo().setIsRecommend("-1");
						} else {
							throw new Exception("推荐字段标记错误  ==" + lineStr);
						}

						String categoryOrder = parts[5].trim();
						if (!StringUtils.isEmpty(categoryOrder)) {
							materialRequest.getMaterialPo().setCategoryOrder(categoryOrder);
						} else {
							throw new Exception(" 类别顺序出错 ==" + categoryOrder);
						}
						
						String category = parts[6].trim();
						if (!StringUtils.isEmpty(category)) {
							materialRequest.getMaterialPo().setCategory(category);
						} else {
							throw new Exception(" 类别出错 ==" + category);
						}
						
						String gender = parts[7].trim();
						if (!StringUtils.isEmpty(gender)) {
							materialRequest.getMaterialPo().setGender(gender);
						} else {
							throw new Exception(" 性别出错 ==" + category);
						}

						materialRequest.getMaterialPo().setVersionType(versionType);
						materialRequest.getMaterialPo().setVersionNumber(versionNumber);
						materialRequests.add(materialRequest);
					}
				}
			} catch (Exception e) {
				throw new Exception("素材配置文件中文件读取错误!" + e.getMessage());
			}
		}
		return materialRequests;
	}

	/*public static void main(String[] args) {
		System.out.println(DateFormatUtils.format(System.currentTimeMillis(), "yyyyMMddHHmmss"));
	}*/
}
